package tech.aistar.day09;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.Set;

/**
 * 本类用来演示: 贪吃蛇
 *
 * @author: success
 * @date: 2022/7/28 2:19 下午
 */
public class SnakeGame {
    //随意定义一个行列 - 界面的长和宽
    public static final int ROWS = 20;
    public static final int COLS = 20;

    //维护一个食物的集合 - 无序不可重复
    Set<Node> foods = new HashSet<>();

    //维护一个蛇的对象
    private Snake snake;

    public Snake getSnake() {
        return snake;
    }

    public SnakeGame(){
        //组合关系
        this.snake = new Snake();
        //进行一些初始化的工作 - 食物
        initFoods(3);
    }

    //随机生成事务.
    private void initFoods(int count) {
        //填充foods

        while(foods.size()<count){
            //纵方向 - 行 [0,20)  [1,18]
            int i = (int) (Math.random()*(ROWS-2)+1);
            int j = (int) (Math.random()*(COLS-2)+1);

            //判断i,j是否在蛇身上
            if(snake.containsNode(i,j)){
                continue;
            }
            //将i,j放入到foods
            foods.add(new Node(i,j));//如果出现重复的,则拒绝添加
        }
    }

    //初始化游戏的界面
    public void start(){
        for (int i = 0; i < ROWS; i++) {
            for (int j = 0; j < COLS; j++) {
                if(i==0 || i==ROWS-1 || j==0 || j==COLS-1){
                    System.out.printf("%2s","*");
                }else if(snake.containsNode(i,j)){
                    System.out.printf("%2s","#");
                }else if(foods.contains(new Node(i,j))){
                    System.out.printf("%2s","0");
                }else{
                    System.out.printf("%2s"," ");
                }
            }
            System.out.println();
        }
    }

    public class Snake{//蛇的内部类
        //定义蛇身
        private LinkedList<Node> snake = new LinkedList<>();

        //定义一个方向
        public static final int UP = -1;
        public static final int DOWN = 1;
        public static final int LEFT = -2;
        public static final int RIGHT = 2;

        private int dir;

        //构造方法 - 初始化蛇身设置默认的方向
        public Snake(){
            snake.add(new Node(5,6));
            snake.add(new Node(5,7));
            snake.add(new Node(5,8));

            dir = LEFT;
        }

        public boolean containsNode(int x,int y){
            return snake.contains(new Node(x,y));
        }

        //走一步
        public void step(int dir){
            if(this.dir + dir == 0){
                throw new RuntimeException("sorry,不能反方向执行!Game Over~~~");
            }
            this.dir = dir;
            step();
        }

        //定义一个走一步
        public void step(){
            //获取蛇头
            Node header = snake.getFirst();

            int i = header.getX()+this.dir%2; // -1 1
            int j = header.getY()+this.dir/2;//-2 2

            //int i = header.getX();//行
            //int j = header.getY();//列
            //判断方向
            //switch (dir){
            //    case UP:
            //        i--;
            //        break;
            //    case DOWN:
            //        i++;
            //        break;
            //    case LEFT:
            //        j--;
            //        break;
            //    case RIGHT:
            //        j++;
            //        break;
            //}
            //新的节点
            header = new Node(i,j);

            //判断蛇身是否包含header
            if(containsNode(i,j)){
                throw new RuntimeException("sorry,撞到自己!Game Over~~~");
            }

            //将这个新的节点放入到蛇头
            snake.addFirst(header);

            //判断header是否属于食物的节点
            //如果属于食物的节点
            //1. 删除尾巴
            //2. 删除食物
            if(foods.remove(header)){//成功删除,返回true
                return;
            }

            //删除尾节点
            snake.removeLast();
        }
    }
}
class SnakeGameTest{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        SnakeGame snakeGame = new SnakeGame();
        SnakeGame.Snake snake = snakeGame.getSnake();

        do{
            snakeGame.start();
            System.out.println("w->上 s->下 a->左 d->右");
            String dir = sc.nextLine();
            switch (dir){
                case "w":
                    snake.step(SnakeGame.Snake.UP);
                    break;
                case "s":
                    snake.step(SnakeGame.Snake.DOWN);
                    break;
                case "a":
                    snake.step(SnakeGame.Snake.LEFT);
                    break;
                case "d":
                    snake.step(SnakeGame.Snake.RIGHT);
                    break;
                default:
                    snake.step();
            }
            if(snakeGame.foods.size()==0){
                System.out.println("恭喜您通关了!");
                snakeGame.start();
                break;
            }
        }while(true);
    }
}